package org.zjx.net.download;

import org.zjx.log.LogLevel;
import org.zjx.log.Logger;

import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

public class DownloadUtils {
    private static Logger logger = Logger.getLogger();

    public interface DownloadCallback {
        void onProgress(int progress);  // 下载进度
        void onSuccess(File file);      // 下载成功
        void onFailure(Exception e);    // 下载失败
    }

    /**
     * 下载文件，支持断点续传
     *
     * @param fileUrl   下载文件的 URL
     * @param destFile  下载保存的目标文件
     * @param callback  下载进度回调接口
     */
    public static void downloadFile(String fileUrl, File destFile, DownloadCallback callback) {
        // 直接创建并启动线程来执行下载任务
        new Thread(new DownloadTask(fileUrl, destFile, callback)).start();
    }

    /**
     * 内部下载任务，支持断点续传
     */
    private static class DownloadTask implements Runnable {
        private String fileUrl;
        private File destFile;
        private DownloadCallback callback;
        private Exception exception;

        public DownloadTask(String fileUrl, File destFile, DownloadCallback callback) {
            this.fileUrl = fileUrl;
            this.destFile = destFile;
            this.callback = callback;
        }

        @Override
        public void run() {
            RandomAccessFile outputStream = null;
            InputStream inputStream = null;
            HttpURLConnection connection = null;

            try {
                // 获取文件的已有大小，用于断点续传
                long downloadedLength = 0;
                if (destFile.exists()) {
                    downloadedLength = destFile.length();
                }

                URL url = new URL(fileUrl);
                connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.setRequestProperty("Range", "bytes=" + downloadedLength + "-"); // 断点续传
                connection.connect();

                int responseCode = connection.getResponseCode();
                if (responseCode != HttpURLConnection.HTTP_PARTIAL && responseCode != HttpURLConnection.HTTP_OK) {
                    logger.log("DownloadTask", LogLevel.ERROR, "Invalid response code: " + responseCode);
                    throw new Exception("Invalid response code: " + responseCode);
                }

                inputStream = connection.getInputStream();
                outputStream = new RandomAccessFile(destFile, "rw");
                outputStream.seek(downloadedLength); // 设置写入位置

                byte[] buffer = new byte[1024];
                int bytesRead;
                long totalBytesRead = downloadedLength;
                long contentLength = connection.getContentLength() + downloadedLength;

                // 下载文件并更新进度
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                    totalBytesRead += bytesRead;

                    // 计算下载进度并回调
                    int progress = (int) ((totalBytesRead * 100) / contentLength);
                    if (callback != null) {
                        callback.onProgress(progress); // 更新进度
                    }
                }
                logger.log("DownloadTask", LogLevel.INFO, "Http download Log: success.");

                // 下载成功后调用成功回调
                if (callback != null) {
                    callback.onSuccess(destFile);
                }
            } catch (Exception e) {
                logger.log("DownloadTask", LogLevel.ERROR, "Http download Log: failed.");
                exception = e;
                // 下载失败时调用失败回调
                if (callback != null) {
                    callback.onFailure(exception);
                }
            } finally {
                try {
                    if (inputStream != null) {
                        inputStream.close();
                    }
                    if (outputStream != null) {
                        outputStream.close();
                    }
                    if (connection != null) {
                        connection.disconnect();
                    }
                } catch (Exception e) {
                    if (callback != null) {
                        callback.onFailure(e); // 关闭流时出错
                    }
                }
            }
        }
    }
}
